/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.japo.java.matisse.samples;

import java.awt.Image;
import java.io.FileReader;
import java.io.FileWriter;
import java.net.ServerSocket;
import java.net.URL;
import java.util.Properties;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;

/**
 *
 * @author José A. Pacheco Ondoño
 */
public class VentanaUnicaSocket extends javax.swing.JFrame {
    // ---

    // Ficheros auxiliares de la aplicacion
    private final String FICHERO_INI = "config.ini";

    // Propiedades de la aplicacion
    private final Properties propiedades = new Properties();

    // Referencia al ServerSocket de ejecución única
    private ServerSocket ss = null;

    public VentanaUnicaSocket() {
        iniciarAnterior();
        initComponents();
        iniciarPosterior();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Ventana única ServerSocket");
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 282, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 153, Short.MAX_VALUE)
        );

        setSize(new java.awt.Dimension(300, 200));
        setLocationRelativeTo(null);
    }// </editor-fold>//GEN-END:initComponents

    private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
        try {
            // Guarda las propiedades 
            guardarPropiedades();
        } catch (Exception e) {
            // Muestra la excepción encontrada
            JOptionPane.showMessageDialog(this, e.toString());

            // Termina el programa
            terminarPrograma();
        }

    }//GEN-LAST:event_formWindowClosing

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /*
         * Set the Nimbus look and feel
         */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /*
         * If Nimbus (introduced in Java SE 6) is not available, stay with the
         * default look and feel. For details see
         * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(VentanaUnicaSocket.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(VentanaUnicaSocket.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(VentanaUnicaSocket.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(VentanaUnicaSocket.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /*
         * Create and display the form
         */
        java.awt.EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new VentanaUnicaSocket().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    // End of variables declaration//GEN-END:variables

    private void iniciarPosterior() {
        // Se aplican las propedades guardadas
        restaurarEstadoVentana();

        // Establecer el panel de fondo
        ponerPanelFondo();
    }

    private void activarInstancia() throws Exception {
        // Fichero de bloqueo predeterminado
        final int PUERTO_LCK = 54321;

        // Puerto de bloqueo
        int puertoBloqueo = obtenerPropiedadEntero("bloqueo", PUERTO_LCK);

        // Abre un ServerSocket al puerto de bloqueo
        ss = new ServerSocket(puertoBloqueo);
    }

    private void terminarPrograma() {
        setVisible(false);
        dispose();
        System.exit(0);
    }

    private void cargarPropiedades() {
        try (FileReader fr = new FileReader(FICHERO_INI)) {
            // Carga las propiedades desde el fichero
            propiedades.load(fr);
        } catch (Exception e) {
            System.out.println(e);
        }
    }

    private void restaurarEstadoVentana() {
        // Posicion X de la ventana
        int x = this.getLocation().x;
        x = obtenerPropiedadEntero("x", x);

        // Posicion Y de la ventana
        int y = this.getLocation().y;
        y = obtenerPropiedadEntero("y", y);

        // Ancho de la ventana
        int ancho = this.getSize().width;
        ancho = obtenerPropiedadEntero("ancho", ancho);

        // Alto de la ventana
        int alto = this.getSize().height;
        alto = obtenerPropiedadEntero("alto", alto);

        // Estado de la ventana
        int estado = this.getExtendedState();
        estado = obtenerPropiedadEntero("estado", estado);

        // Aplicar propiedades
        this.setBounds(x, y, ancho, alto);
        this.setExtendedState(estado);
    }

    private void guardarPropiedades() {
        // Proceso de salvaguarda de propiedades
        try (FileWriter fw = new FileWriter(FICHERO_INI)) {
            // Actualizar propiedades
            actualizarPropiedades();

            // Carga las propiedades
            propiedades.store(fw, null);
        } catch (Exception e) {
            System.out.println(e);
        }
    }

    private void actualizarPropiedades() {
        // Posicion X de la ventana
        int x = this.getLocation().x;
        propiedades.setProperty("x", x + "");

        // Posicion Y de la ventana
        int y = this.getLocation().y;
        propiedades.setProperty("y", y + "");

        // Ancho de la ventana
        int ancho = this.getSize().width;
        propiedades.setProperty("ancho", ancho + "");

        // Alto de la ventana
        int alto = this.getSize().height;
        propiedades.setProperty("alto", alto + "");

        // Estado de la ventana
        int estado = this.getExtendedState();
        propiedades.setProperty("estado", estado + "");
    }

    private void ponerPanelFondo() {
        // Fichero de fondo predeterminado
        final String FICHERO_BAK = "fondo.jpg";

        // Nombre del fichero gráfico
        String ficheroFondo = propiedades.getProperty("fondo");
        if (ficheroFondo == null) {
            propiedades.setProperty("fondo", FICHERO_BAK);
            ficheroFondo = FICHERO_BAK;
        }

        // Crea una URL a la imagen gráfica de fondo
        URL urlFondo = getClass().getResource(ficheroFondo);

        // Crea un objeto Image a partir de la url
        Image imagenFondo = new ImageIcon(urlFondo).getImage();

        // Instancia el panel de fondo a partir de Image
        PanelFondo pf = new PanelFondo(imagenFondo);

        // Establece el panel de fondo como panel contenedor
        this.setContentPane(pf);
    }

    private int obtenerPropiedadEntero(String propiedad, int predeterminado) {
        // Valor a devolver
        int i = predeterminado;

        try {
            // Obtiene la propiedad actual
            String valor = propiedades.getProperty(propiedad);

            // Analiza si la propiedad es nula
            if (valor != null) {
                // Genera un nuevo Integer
                i = Integer.parseInt(valor);
            } else {
                // Establece la propiedad con el valor predeterminado
                propiedades.setProperty(propiedad, predeterminado + "");
            }
        } catch (NumberFormatException e) {
            // Muestra la excepcion
            System.out.println(e);

            // Establece la propiedad con el valor predeterminado
            propiedades.setProperty(propiedad, predeterminado + "");
        }

        // Devuelve el valor
        return i;
    }

    private void iniciarAnterior() {
        // Carga las propiedades
        cargarPropiedades();

        // Ejecución unica
        validarInstanciaUnica();
    }

    private void validarInstanciaUnica() {
        try {
            activarInstancia();
        } catch (Exception ex) {
            terminarPrograma();
        }
    }
}
